package com.colin.userservice.service.impl;

import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.crypto.digest.MD5;
import com.colin.bean.User;
import com.colin.response.R;
import com.colin.response.RCM;
import com.colin.userservice.exception.RegisterException;
import com.colin.userservice.exception.sub.PasswordErrorException;
import com.colin.userservice.exception.sub.UserNotExistException;
import com.colin.userservice.exception.sub.UsernameExistException;
import com.colin.userservice.mapper.UserMapper;
import com.colin.userservice.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private Snowflake snowflake;

    @Override
    public R<Boolean> checkUsernameIsExist(String username) {
        Long id = userMapper.selectIdByUsername(username);
        if(id != null) {
            log.error("用户名：{}已被使用", username);
            throw new UsernameExistException(username);
        }
        return null;
    }

    /**
     * 二次加盐加密
     * @param user
     * @return
     */
    @Override
    public R<Boolean> doRegister(User user) {
        String username = user.getUsername();
        //雪花算法生成全局id
        long id =snowflake.nextId();
        user.setId(id);
        log.info("雪花算法生成id:{}",id);
        //生成随机盐
        RandomGenerator randomGenerator = new RandomGenerator(6);
        String salt = Base64.encode(randomGenerator.generate()) ;
        user.setSalt(salt);
        log.info("随机生成盐：{}",salt);
        //二次加盐加密 password：salt -> md5(password:salt)
        MD5 md5 = MD5.create();
        String finalPassword = md5.digestHex16(user.getPassword() + ":" + salt, StandardCharsets.UTF_8);
        log.info("最终密码：{}",finalPassword);
        //封装user数据
        user.setPassword(finalPassword);
        user.setSalt(salt);
        user.setAvatarUrl(null);
        user.setSignupTime(LocalDateTime.now());
        user.setLevel(1);
        user.setDescription("这个人很懒，还没有个性签名");
        user.setExp(0);
        user.setSex("男");
        user.setBirthday(null);
        user.setAddress(null);
        Boolean insertResult = userMapper.insertUser(user);
        if(!insertResult) {
            log.error("用户名：{}注册失败 结果为false 抛出异常RegisterException",username);
            throw new RegisterException(RCM.USER_REGISTER_ERROR.getMessage());
        }
        return R.ok(insertResult);
    }

    /**
     * 登录逻辑
     * 1.验证当前用户是否能登录
     *
     * 2.能登录的情况下 服务端怎么去保存用户登态
     * 长短Token SaToken
     * @param user
     * @return
     */
    @Override
    public R<User> doLogin(User user) {
        //获得用户的盐
        String salt = userMapper.selectSaltByUsername(user.getUsername());
        String username =user.getUsername();
        log.info("用户名：{}对应的salt：{}", username, salt);
        if (salt == null) {
            log.error("用户名为：{}的用户不存在", user.getUsername());
            throw new UserNotExistException(RCM.USER_NOT_EXISTS.getMessage());
        }
        //二次加盐加密
        MD5 md5 = MD5.create();
        String finalPassword = md5.digestHex16(user.getPassword() + ":" + salt, StandardCharsets.UTF_8);
        log.info("最终密码为{}", finalPassword);
        //用二次加盐加密的username和password进行查询
        user = userMapper.selectUserByUsernameAndPassword(username, finalPassword);
        if(user == null) {
            log.error("用户名为：{}的用户密码错误", username);
            throw new PasswordErrorException(RCM.USER_PASSWORD_ERROR.getMessage());
        }
        //处理敏感信息，避免将用户数据传回前端被捕获
        user.setPassword(null);
        user.setSalt(null);
        return R.ok(user);
    }
}
